package nl.tudelft.jpacman.level;

import nl.tudelft.jpacman.board.Unit;
import nl.tudelft.jpacman.npc.Ghost;
import nl.tudelft.jpacman.points.PointCalculator;


public class PlayerCollisions implements nl.tudelft.jpacman.level.CollisionMap {

    private PointCalculator pointCalculator;

    /**
     * Create a simple player-based collision map, informing the
     * point calculator about points to be added.
     *
     * @param pointCalculator
     *             Strategy for calculating points.
     */
    public PlayerCollisions(PointCalculator pointCalculator) {
        this.pointCalculator = pointCalculator;
    }

    @Override
    public void collide(Unit mover, Unit collidedOn) {
        if (mover instanceof nl.tudelft.jpacman.level.Player) {
            playerColliding((nl.tudelft.jpacman.level.Player) mover, collidedOn);
        }
        else if (mover instanceof Ghost) {
            ghostColliding((Ghost) mover, collidedOn);
        }
        else if (mover instanceof nl.tudelft.jpacman.level.Pellet) {
            pelletColliding((nl.tudelft.jpacman.level.Pellet) mover, collidedOn);
        }
    }

    private void playerColliding(nl.tudelft.jpacman.level.Player player, Unit collidedOn) {
        if (collidedOn instanceof Ghost) {
            playerVersusGhost(player, (Ghost) collidedOn);
        }
        if (collidedOn instanceof nl.tudelft.jpacman.level.Pellet) {
            playerVersusPellet(player, (nl.tudelft.jpacman.level.Pellet) collidedOn);
        }
    }

    private void ghostColliding(Ghost ghost, Unit collidedOn) {
        if (collidedOn instanceof nl.tudelft.jpacman.level.Player) {
            playerVersusGhost((nl.tudelft.jpacman.level.Player) collidedOn, ghost);
        }
    }

    private void pelletColliding(nl.tudelft.jpacman.level.Pellet pellet, Unit collidedOn) {
        if (collidedOn instanceof nl.tudelft.jpacman.level.Player) {
            playerVersusPellet((nl.tudelft.jpacman.level.Player) collidedOn, pellet);
        }
    }


    /**
     * Actual case of player bumping into ghost or vice versa.
     *
     * @param player
     *          The player involved in the collision.
     * @param ghost
     *          The ghost involved in the collision.
     */
    public void playerVersusGhost(nl.tudelft.jpacman.level.Player player, Ghost ghost) {
        pointCalculator.collidedWithAGhost(player, ghost);
        player.setAlive(false);
        player.setKiller(ghost);
    }

    /**
     * Actual case of player consuming a pellet.
     *
     * @param player
     *           The player involved in the collision.
     * @param pellet
     *           The pellet involved in the collision.
     */
    public void playerVersusPellet(nl.tudelft.jpacman.level.Player player, nl.tudelft.jpacman.level.Pellet pellet) {
        pointCalculator.consumedAPellet(player, pellet);
        pellet.leaveSquare();
    }

}
